package com.juli.school.utils.log.filter;

import java.io.IOException;
import java.util.Date;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.juli.school.utils.core.diagnostic.Profiler;
import com.juli.school.utils.core.runtime.MdcHolder;
import com.juli.school.utils.core.runtime.ProductContext;
import com.juli.school.utils.core.runtime.ProductContextHolder;
import com.juli.school.utils.core.runtime.ProductEnvironment;
import com.juli.school.utils.core.utils.IPUtils;
import com.juli.school.utils.log.utils.HttpHeaderUtils;

/**
 * @Description: http请求性能拦截
 * @ClassName: PerformanceWebFilter
 * @author gaoxiang
 * @date 2015年11月24日 下午10:46:19
 */
public class PerformanceWebFilter extends AbstractFilter {
	
	private final static Logger logger = LoggerFactory.getLogger("PERFORM");
	
	/**
	 * @Fields threshold : 以毫秒表示的阈值
	 */
	private int threshold = 1000;
	
	@Override
	protected void doFilterLogic(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		// 产品环境初始化
		productContextInit(httpServletRequest);
		// MDC日志初始化
		MdcHolder.init(ProductContextHolder.getProductContext());
		Profiler.start("Invoking URL: " + httpServletRequest.getRequestURI());
		try {
			chain.doFilter(request, response);
		} finally {
			//判断是否输出web调用日志
			performOutput(httpServletRequest);
			// 清除线程相关的资源
			Profiler.reset();
			ProductContextHolder.clean();
			MdcHolder.clean();
		}
	}
	
	@Override
	protected void doInit(FilterConfig filterConfig) throws ServletException {
		String sthreshold = filterConfig.getInitParameter("threshold");
		if (StringUtils.isNotBlank(sthreshold)) {
			threshold = NumberUtils.toInt(sthreshold);
		}
		logger.debug("init threshold = " + threshold);
	}
	
	/**
	 * @Description: 产品环境初始化
	 * @author gaoxiang
	 * @date 2016年12月28日 下午7:03:06
	 */
	private void productContextInit(HttpServletRequest httpServletRequest) {
		ProductContext productContext = ProductContextHolder.getProductContext();
		ProductEnvironment environment = productContext.getEnvironment();
		// 客户端IP
		environment.setClientIp(HttpHeaderUtils.getRemoteHost(httpServletRequest));
		// 服务端IP
		environment.setServerIp(IPUtils.getIp4Single());
		// 服务器端名称
		environment.setServerName(httpServletRequest.getServerName());
		// sessionID
		environment.setSessionId(httpServletRequest.getSession().getId());
		// 用户操作时间
		productContext.setTime(new Date());
		// 设置来源URL
		productContext.setReferer(HttpHeaderUtils.getReferer(httpServletRequest));
		// 设置访问URL
		productContext.setUrl(HttpHeaderUtils.getRequestURLWithParameter(httpServletRequest));
	}
	
	/**
	 * @Description: 性能日志输出
	 * @author gaoxiang
	 * @date 2016年12月28日 下午7:02:53
	 */
	private void performOutput(HttpServletRequest httpServletRequest){
		Profiler.release();
		long elapseTime = Profiler.getDuration();
		// 如果调用时间超过阈值 则进行超时详情日志输出
		if (elapseTime > threshold) {
			StringBuilder builder = new StringBuilder();
			builder.append("URL:");
			builder.append(HttpHeaderUtils.getRequestURLWithParameter(httpServletRequest));
			// 阈值时间
			builder.append(" threshold = ").append(threshold).append("ms,");
			// 实际执行时间为
			builder.append(" used = ").append(elapseTime).append("ms.\r\n");
			// 追加web下层调用超时堆栈
			builder.append(Profiler.dump());
			logger.info(builder.toString());
		}
	}
}
